package parser

import (
	"bytes"

	"vitess.io/vitess/go/vt/sqlparser"
)

func ColNameToString(expr *sqlparser.ColName) string {
	return expr.Name.String()
}

func LiteralToString(val *sqlparser.Literal) string {
	switch val.Type {
	case sqlparser.IntVal:
		return val.Val
	case sqlparser.DecimalVal:
		return val.Val
	case sqlparser.FloatVal:
		return val.Val
	default:
		return "'" + val.Val + "'"
	}
}
func exprToString(buf *bytes.Buffer, expr sqlparser.SQLNode) error {
	switch v := expr.(type) {
	case *sqlparser.ComparisonExpr:
		err := exprToString(buf, v.Left)
		if err != nil {
			return err
		}
		buf.WriteString(" " + v.Operator.ToString() + " ") //比较运算符
		err = exprToString(buf, v.Right)
		if err != nil {
			return err
		}
		return nil
	case *sqlparser.BinaryExpr:
		switch v.Operator {
		case sqlparser.MultOp, sqlparser.DivOp, sqlparser.ModOp:
			_, left_ok := v.Left.(*sqlparser.BinaryExpr)
			if !left_ok {
				_, left_ok = v.Left.(*sqlparser.FuncExpr)
			}
			if left_ok {
				buf.WriteString("(")
			}
			err := exprToString(buf, v.Left)
			if err != nil {
				return err
			}
			if left_ok {
				buf.WriteString(")")
			}
			buf.WriteString(" " + v.Operator.ToString() + " ") //比较运算符

			_, right_ok := v.Right.(*sqlparser.BinaryExpr)
			if !right_ok {
				_, right_ok = v.Right.(*sqlparser.FuncExpr)
			}
			if right_ok {
				buf.WriteString("(")
			}
			err = exprToString(buf, v.Right)
			if err != nil {
				return err
			}
			if right_ok {
				buf.WriteString(")")
			}
			return nil
		default:
			err := exprToString(buf, v.Left)
			if err != nil {
				return err
			}
			buf.WriteString(" " + v.Operator.ToString() + " ") //比较运算符
			err = exprToString(buf, v.Right)
			if err != nil {
				return err
			}
			return nil
		}
	case *sqlparser.FuncExpr:
		if v.Qualifier.String() != "" {
			buf.WriteString(v.Qualifier.String() + ".")
		}
		buf.WriteString(v.Name.String())
		buf.WriteString("(")
		for i, e := range v.Exprs {
			if i > 0 {
				buf.WriteString(", ")
			}
			err := exprToString(buf, e)
			if err != nil {
				return err
			}
		}
		buf.WriteString(")")
		return nil
	case *sqlparser.AliasedExpr:
		err := exprToString(buf, v.Expr)
		if err != nil {
			return err
		}
		//if v.As.String() != "" {
		//	buf.WriteString(" as ")
		//	buf.WriteString(v.As.String())
		//}
		return nil
	case *sqlparser.AndExpr:
		err := exprToString(buf, v.Left)
		if err != nil {
			return err
		}
		buf.WriteString(" and ")
		if _, ok := v.Right.(*sqlparser.OrExpr); ok {
			buf.WriteString("(")
			err = exprToString(buf, v.Right)
			buf.WriteString(")")
		} else {
			err = exprToString(buf, v.Right)
		}
		return err
	case *sqlparser.OrExpr:
		err := exprToString(buf, v.Left)
		if err != nil {
			return err
		}
		buf.WriteString(" or ")
		err = exprToString(buf, v.Right)
		if err != nil {
			return err
		}
		return nil
	case sqlparser.ValTuple:
		buf.WriteString("#[")
		for i, val := range v {
			if i > 0 {
				buf.WriteString(",")
			}
			value := val.(*sqlparser.Literal)
			switch value.Type {
			case sqlparser.IntVal:
				buf.WriteString(value.Val)
			case sqlparser.DecimalVal:
				buf.WriteString(value.Val)
			case sqlparser.FloatVal:
				buf.WriteString(value.Val)
			default:
				buf.WriteString("'" + value.Val + "'")
			}
		}
		buf.WriteString("]#")
		return nil
	case *sqlparser.ColName:
		buf.WriteString(ColNameToString(v))
		return nil
	case *sqlparser.Literal:
		buf.WriteString(LiteralToString(v))
		return nil
	}
	return nil
}
